package com.huya.k12.translate.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;

import com.huya.k12.translate.model.entity.Word;
import com.huya.k12.translate.model.util.StandaloneWriter;
import com.huya.k12.translate.model.vo.WordVo;
//import com.huya.k12.translate.service.WordService;

import ch.qos.logback.core.net.SyslogOutputStream;

@Component
public class XMLUtil {
	
	private Logger logger = Logger.getLogger(XMLUtil.class);
	private Map<String,WordVo> wordMap; 
	private List<Word> wordList;
	
	private List<Word>addWord;
	private List<Word>updateWord;
	private List<Word>deleteWord;
	
	private List<File> newFileList;
	
//	@Autowired
//	private WordService wordService;
	
	private Map<String,Map<String,Object>> documentMap;
	
	@Value("${svn.workingCopyPath}")
	private String workingCopyPath;
	
	
	@Value("${xml.path}")
	private String path;
	
	
	
	public List<File> getNewFileList() {
		return newFileList;
	}

	public void setNewFileList(List<File> newFileList) {
		this.newFileList = newFileList;
	}

	public void loadDefaultXml(){
		String filePath = workingCopyPath + path + "//values";
		File fileDir = new File(filePath);
		wordMap = new HashMap<String,WordVo>();
		if(fileDir.isDirectory()){
			for(File file: fileDir.listFiles()){
				if(file.getName().startsWith("strings")){
					Document document  = getDocument(file);
					if(document != null){
						String fileName = file.getName();
						Map<String,String> map = read(document);
						for(String key : map.keySet()){
							WordVo wordVo = new WordVo();
							Map<String,String> languageMap = new HashMap<String,String>();
							wordVo.setWordId(key);
							wordVo.setFileName(fileName);
							languageMap.put("en", map.get(key));
							wordVo.setLanguage(languageMap);
							wordMap.put(key, wordVo);
						}
					}
				}
			}
		}
	}
	
	public void loadOtherXml(){
		String filePath = workingCopyPath + path;
		File parentFile = new File(filePath);
		if(parentFile.isDirectory()){
			for(File fileDir : parentFile.listFiles()){
				if(fileDir.getName().startsWith("values-")){
					String ab  = fileDir.getName().substring(7);
					for(File file : fileDir.listFiles()){
						if(file.getName().startsWith("strings")){
							Document document =  getDocument(file);
							if(document != null){
								Map<String, String> map = read(document);
								for(String key : map.keySet()){
									WordVo wordVo = wordMap.get(key);
									if(wordVo != null){
										Map<String,String> languageMap = wordVo.getLanguage();
										languageMap.put(ab, map.get(key)); 
									}else{
										logger.error("can't find the key in default file:"+file+key);
									}
								}
							}
						}
					}
					
				}
				
			}
		}
	}
	
	
	public Document getDocument(File file){
		Document document = null;
		SAXReader reader = new SAXReader();
		try {
			document = reader.read(file);
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			logger.error(e.getMessage(), e);
			return null;
		}
		return document;
	}
	
	public Document getDocument(InputStream inputStream){
		Document document = null;
		SAXReader reader = new SAXReader();
		try {
			document = reader.read(inputStream);
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			logger.error(e.getMessage(), e);
			return null;
		}
		return document;
	}
	
	public Map<String,String> read(Document document){
		Map<String,String>map = new HashMap<String,String>();
		Element root = document.getRootElement();
		List<Element>nodes = root.elements();
		for(Element el: nodes){
			String key =el.attributeValue("name");
			String value=el.getText();
//			List<Element> childNodes = el.elements();
//			if(childNodes!=null&&childNodes.size()>0){
//				for(Element element : childNodes){
//					value+=element.asXML();
//				}
//			}else{
//				value += el.getText();
//			}
			
			map.put(key, value);
		}
		return map;
	}
	
	public void initDocument(){
		String filePath = workingCopyPath + path;
		File parentFile = new File(filePath);
		documentMap = new HashMap<String, Map<String, Object>> ();
		if(parentFile.isDirectory()){
			for(File fileDir : parentFile.listFiles()){
				if(fileDir.getName().startsWith("values")){
					String ab = "";
					if(fileDir.getName().equals("values")){
						ab="en";
					}else{
						ab = fileDir.getName().substring(7);
					}
					for(File file: fileDir.listFiles()){
						if(file.getName().startsWith("strings")){
							Document document = getDocument(file);
							Map<String,Object> map = new HashMap<String, Object>();
							if(document!=null){
								map.put("document", document);
								map.put("isReWrite", false);
								map.put("filePath", file.getPath());
								documentMap.put(ab+"_"+file.getName(), map);
							}
						}
					}
				}
			}
		}
		
	}

	public Map<String, WordVo> getWordMap() {
		return wordMap;
	}

	public void setWordMap(Map<String, WordVo> wordMap) {
		this.wordMap = wordMap;
	}

	public List<Word> getWordList() {
		wordList = new ArrayList<Word>();
		for(String key : wordMap.keySet()){
			WordVo wordVo = wordMap.get(key);
			if(wordVo != null){
				Word word = new Word();
				Map<String,String> languageMap = wordVo.getLanguage();
				word.setWordId(wordVo.getWordId());
				word.setFileName(wordVo.getFileName());
				word.setEn(languageMap.get("en"));
				word.setAr(languageMap.get("ar"));
				word.setDe(languageMap.get("de"));
				word.setEs(languageMap.get("es"));
				word.setFr(languageMap.get("fr"));
				word.setHi(languageMap.get("hi"));
				word.setIndia(languageMap.get("in"));
				word.setIt(languageMap.get("it"));
				word.setJa(languageMap.get("ja"));
				word.setKo(languageMap.get("ko"));
				word.setMs(languageMap.get("ms"));
				word.setPt(languageMap.get("pt"));
				word.setRu(languageMap.get("ru"));
				word.setTh(languageMap.get("th"));
				word.setTl(languageMap.get("tl"));
				word.setTr(languageMap.get("tr"));
				word.setUr_rPK(languageMap.get("ur-rPK"));
				word.setVi(languageMap.get("vi"));
				word.setZh(languageMap.get("zh"));
				word.setZh_rCN(languageMap.get("zh-rCN"));
				word.setZh_rSG(languageMap.get("zh-rSG"));
				wordList.add(word);
			}
		}
		return wordList;
	}

	public void setWordList(List<Word> wordList) {
		this.wordList = wordList;
	}



	
	
	public Map<String, Map<String, Object>> getDocumentMap() {
		return documentMap;
	}

	public void setDocumentMap(Map<String, Map<String, Object>> documentMap) {
		this.documentMap = documentMap;
	}
	
	public void createFilePath(){
		
	}

	public void nodifyDoc(List<Word> wordList) throws Exception{
		if(wordList != null && wordList.size() > 0){
			initDocument();
			newFileList = new ArrayList<File>();
			for(Word word : wordList){
				Map<String, String> language = languageMap(word);
				String fileName = word.getFileName();
				for(String key:language.keySet()){
					String value = language.get(key);
					String documentKey = key+"_"+fileName;
					if(StringUtils.isNotBlank(value)){
						if(documentMap.get(documentKey)!=null){
							Map<String,Object> map = documentMap.get(documentKey);
							Document document = (Document) map.get("document");
							Element root = document.getRootElement();
							List<Element> elements = root.elements();
							boolean isAdd = true;
							for(Element element : elements){
								if(element.attributeValue("name").equals(word.getWordId())){
									if(element.getText().equals(value)){
										isAdd=false;
									}else{
										element.setText(value);
										logger.info("change:"+"wordId:"+word.getWordId()+" "+"language:"+key+" "+"word"+value);
										isAdd=false;
										map.put("isReWrite", true);
									}
									break;
								}
							}
							if(isAdd){
								
								Element addElement = root.addElement("string");
								addElement.addAttribute("name", word.getWordId());
								addElement.setText(value);
								map.put("isReWrite", true);
								logger.info("add:"+"wordId:"+word.getWordId()+" "+"word:"+value);
							}
						}else{
							String newPath = workingCopyPath + path + "/values-"+key+"/"+fileName;
							Document newDocument = DocumentHelper.createDocument();
							Element newRoot = DocumentHelper.createElement("resources");
							newRoot.addAttribute("xmlns:tool", "http://schemas.android.com/tools");
							newDocument.setXMLEncoding("utf-8");
							newDocument.setRootElement(newRoot);
							Element node = DocumentHelper.createElement("string");
							node.addAttribute("name", word.getWordId());
							node.setText(value);
							newRoot.add(node);
							reWrite(newPath, newDocument);
							HashMap<String,Object> newMap = new HashMap<String, Object>();
							newMap.put("document", newDocument);
							newMap.put("isReWrite", false);
							newMap.put("filePath", newPath);
							documentMap.put(key+"_"+fileName, newMap);
							newFileList.add(new File(newPath));
							logger.info("create new file:"+newPath);
						}
					}else{
						Map<String,Object> map = documentMap.get(documentKey);
						if(map!=null){
							Document document = (Document) map.get("document");
							Element root = document.getRootElement();
							List<Element> elements = root.elements();
							for(Element element : elements){
								if(element.attributeValue("name").equals(word.getWordId())){
									String text = element.getText();
									if(StringUtils.isNotBlank(text)){
										element.setText("");
										break;
									}
								}
							}
						}
					}
				}
//				for(String filePath : documentMap.keySet()){
//					Map<String,Object> map = documentMap.get(filePath);
//					Document document = (Document) map.get("document");
//					String ab = (String) map.get("ab");
//					String fileName = (String) map.get("fileName");
//					Map<String,String>language = languageMap(word);
//					
//					if(fileName.equals(word.getFileName())){
//						Element root = document.getRootElement();
//						List<Element> elements = root.elements();
//						boolean isAdd = true;
//						if(StringUtils.isNotBlank(language.get(ab))){
//							for(Element element : elements){
//								if(element.attributeValue("name").equals(word.getWordId())){
//									if(element.getText().equals(language.get(ab))){
//										isAdd = false;
//										break;
//									}else{
//										element.setText(language.get(ab));
//										logger.info("change:"+"wordId:"+word.getWordId()+" "+"language:"+ab+" "+"word:"+language.get(ab));
//										isAdd = false;
//										map.put("isReWrite", true);
//										break;
//									}
//								}
//							}
//							if(isAdd){
//								Element addElement = root.addElement("string");
//								addElement.addAttribute("name", word.getWordId());
//								addElement.setText(language.get(ab));
//								map.put("isReWrite", true);
//								logger.info("add:"+"wordId:"+word.getWordId()+" "+"word:"+language.get(ab));
//							}
//						}
//					}
//				}
			}
			for(String key:documentMap.keySet()){
				Map<String, Object> map = documentMap.get(key);
				boolean isReWrite = (Boolean) map.get("isReWrite");
				if(isReWrite){
					String filePath = (String) map.get("filePath");
					Document document = (Document) map.get("document");
					reWrite(filePath, document);
					logger.info("reWrite File have : "+filePath);
				}
			}
		}
	}
	
	public Map<String,String> languageMap(Word word){
		Map<String,String> map = new HashMap<String,String>();
		if(word != null){
			map.put("en", word.getEn());
			map.put("ar", word.getAr());
			map.put("de", word.getDe());
			map.put("es", word.getEs());
			map.put("fr", word.getFr());
			map.put("hi", word.getHi());
			map.put("in", word.getIndia());
			map.put("it", word.getIt());
			map.put("ja", word.getJa());
			map.put("ko", word.getKo());
			map.put("ms", word.getMs());
			map.put("pt", word.getPt());
			map.put("ru", word.getRu());
			map.put("th", word.getTh());
			map.put("tl", word.getTl());
			map.put("tr", word.getTr());
			map.put("ur-rPK", word.getUr_rPK());
			map.put("vi", word.getVi());
			map.put("zh", word.getZh());
			map.put("zh-rCN", word.getZh_rCN());
			map.put("zh-rSG", word.getZh_rSG());
		}
		return map;
		
	}
	
	
	public void reWrite(String filePath, Document document) throws Exception{
		try {
			File file = new File(filePath);
			if(!file.exists()){
				file.createNewFile();
			}
			FileOutputStream out = new FileOutputStream(filePath);
			OutputFormat format = OutputFormat.createPrettyPrint();
			format.setEncoding("utf-8");
			StandaloneWriter writer = new StandaloneWriter(out, format);
			writer.write(document);
			writer.flush();
			writer.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			logger.error(e.getMessage(),e);
			throw new Exception(e);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			logger.error(e.getMessage(),e);
			throw new Exception(e);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.error(e.getMessage(),e);
			throw new Exception(e);
		}
	}
	
	
	public Map<String, Word> defaultXMLToMap(){
		Map<String, Word> map = new HashMap<String, Word>();
		String defaultFilePath = workingCopyPath + path + "//values";
		File defaultFileDir = new File(defaultFilePath);
		if(defaultFileDir.isDirectory()){
			for(File defaultFile: defaultFileDir.listFiles()){
				if(defaultFile.getName().startsWith("strings")){
					Document document = getDocument(defaultFile);
					Map<String,String> singleMap = new HashMap<String,String>();
					if(document != null){
						singleMap = read(document);
						for(String key : singleMap.keySet()){
							Word word = new Word();
							word.setWordId(key);
							word.setEn(singleMap.get(key));
							word.setFileName(defaultFile.getName());
							map.put(key,word);
						}
					}
				}
			}
		}
		return map;
	}

//	public Map<String, Word> dbListToMap(){
//		Map<String, Word> map = new HashMap<String, Word>();
//		List<Word> wordList = wordService.listAll();
//		if(wordList!=null && wordList.size() > 0 ){
//			for(Word word : wordList){
//				map.put(word.getWordId(), word);
//			}
//		}
//		return map;
//	}
	
//	public void updateXML(){
//		List<Word> wordList = wordService.listByStatus(1);
//		initDocument();
//		nodifyDoc(wordList);
//	}
	
//	public void updateDB(){
//		Map<String, Word> xmlMap = defaultXMLToMap();
//		Map<String, Word> dbMap = dbListToMap();
//		addWord = new ArrayList<Word>();
//		updateWord = new ArrayList<Word>();
//		deleteWord = new ArrayList<Word>();
//		for(String key : xmlMap.keySet()){
//			Word word= dbMap.get(key);
//			if(word == null){
//				addWord.add(xmlMap.get(key));
//				System.out.println("add:"+xmlMap.get(key).getEn());
//			}
//			else if(!word.getEn().equals(xmlMap.get(key).getEn())){
//				System.out.println("before:"+word.getEn());
//				System.out.println("after:"+xmlMap.get(key).getEn());
//				word.setEn(xmlMap.get(key).getEn());
//				updateWord.add(word);
//			}
//		}
//		for(String key : dbMap.keySet()){
//			Word word = xmlMap.get(key);
//			if(word == null)
//				deleteWord.add(word);
//		}
//	}

	public List<Word> getAddWord() {
		return addWord;
	}

	public void setAddWord(List<Word> addWord) {
		this.addWord = addWord;
	}

	public List<Word> getUpdateWord() {
		return updateWord;
	}

	public void setUpdateWord(List<Word> updateWord) {
		this.updateWord = updateWord;
	}

	public List<Word> getDeleteWord() {
		return deleteWord;
	}

	public void setDeleteWord(List<Word> deleteWord) {
		this.deleteWord = deleteWord;
	}


	
	
	
	

}
